import config from './config'
import axios from 'axios'
import qs from 'qs'

// 不需要授权的api
const freeApis = [
  '/core/authorize/accountLogin',
  '/core/authorize/phoneLogin',
  '/core/authorize/sendVerificationCode',
  '/auth/authorize/accountActive'
]
class SDK{
  constructor(){
    this._delayedCall = [] // 延迟 处理单元
    this._errHanlders = [] // 错误 处理器
    // 创建一个文件上传用的 axios 对象
    this.uploadInst = axios.create({
      baseURL:config.serverAddress,
      timeout:config.timeout,
      headers:{
        'Content-Type' : 'multipart/form-data'
      }
    })
  }
  // 设置token 意味着重新登陆了
  set token(token){
    this._token = token
    // 每次设置token，都需要对延迟调用的 请求 做一次清楚
    if(this._token) // 只有 token有值的时候才需要请求
      this._delayedCall.forEach(params=>{
        this.fetch(params)
      })
    // 处理完清理,每次新的token来之后都要清理下 老的请求,不管token有没有
    if (this._delayedCall.length>0)
      this._delayedCall.splice(0,this._delayedCall.length)
  }
  delDelayedCall(token){
    // 每次设置token，都需要对延迟调用的 请求 做一次清楚
    if(token) // 只有 token有值的时候才需要请求
      this._delayedCall.forEach(params=>{
        this.fetch(params,token)
      })
    // 处理完清理,每次新的token来之后都要清理下 老的请求,不管token有没有
    if (this._delayedCall.length>0)
      this._delayedCall.splice(0,this._delayedCall.length)
  }
  // 注册 事件，提供异常过滤事件
  regErrHanlder(hanlder){
    /**
     * 如：{
     *  errCode : 'token_is_invalid',
     *  action: (err,params) => {}
     * }
     */
    // 结构正确才可以被接纳
    if(hanlder.errCode && hanlder.action)
      this._errHanlders.push(hanlder)
  }

  // api 请求
  fetch(params,token){
    // console.log('记录请求-----------',params,token)
    // 错误没必要这里处理，因为 业务有自己的具体处理方案，比如用户状态会维护自己的token,个人认为
    if (token != null)  this.doRequest(params, token)
    else {
      if (this.authCheck(params.api)) {
        this._delayedCall.push(params)
      } else  this.doRequest(params)
    }
  }

  // 检查是否需要授权
  authCheck(api) {
    return freeApis.findIndex(a => a === api) < 0 // 不存在就 是需要验证的
  }
  doRequest(params, token){
    // Loading.service({fullscreen: true, text: '拼命加载中....'} )
    this.checkParams(params) // 异常处理 二选一
    let sysParams = {
      clientid: config.clientid
    } // 客户端ID
    if (token) sysParams.token = token // 用户token
    let method = params.method ? params.method : config.method
    let timeout = config.timeout;
    let prepareData={
      url:config.serverAddress + params.api,
      header: {
        'Content-Type' : 'application/x-www-form-urlencoded'
      },
      data: {
        ...sysParams,
        ...params.data
      },
      dataType: 'json',
    }
    switch (method) {
      case 'POST':{
        axios.post(prepareData.url,qs.stringify(prepareData.data),{headers:prepareData.header,timeout})
          .then(response =>{
            this.dealResponse(response,params)
          }).catch(error =>{
            console.log('post---------',error)
          if(error.response.data && error.response.data.errCode) this.dealResponse(error.response,params)
          else this.completeSDK(error.response,params)
        })
        break
      }
      case 'upload':{
        this.upload(params.api,prepareData)
          .then(response =>{
          this.dealResponse(response,params)
        }).catch(error =>{
          console.log('upload---------',error)
          if(error.response.data && error.response.data.errCode) this.dealResponse(error.response,params)
          else this.completeSDK(error.response,params)
        })
        break
      }
      default:
        axios.get(prepareData.url,{params:prepareData.data},{timeout})
          .then(response =>{
            this.dealResponse(response,params)
          }).catch(error =>{
          console.log('get---------',error)
          if(error.response.data && error.response.data.errCode) this.dealResponse(error.response,params)
          else this.completeSDK(error.response,params)
        })
        break
    }
  }
  upload(apiName,prepareData){
     return new Promise((resolve,reject)=> {
      // console.log('看看 request',request)
      // 组装formData
      let fd = new FormData()
      fd.append('file',prepareData.data.file,encodeURIComponent(prepareData.data.file.name))
      Object.keys(prepareData.data).forEach(key=>{
        if(key !=='file')
          fd.append(key,prepareData.data[key])
      })
      this.uploadInst.post(apiName,fd)
        .then(response => {
          resolve(response);
        }).catch(error => {
        reject(error);
      });
    })
  }
  //集中处理get，post的respone
  dealResponse(response,params){
    if(response.data.errCode){
      // console.log('delresponse-------',response)
      if(this._errHanlders.length>0) this.doErrHanlder(response,params)
      if(params.fail) params.fail(response.data)
    }else{
      try {
        if(params.success){
          params.success(response.data)
        }
        if(params.complete) params.complete(response.data)
      }catch (e) {
        console.log('截获错误---------',e)
      }
    }
    this.completeSDK(response,params)
  }

  // 错误回调 这里的错误是指 服务器端 的特定错误
  doErrHanlder(res,params){
    console.log('处理指定错误------',res,params)
    if(res.data && res.data.errCode){
      this._errHanlders.forEach(h=>{
        if (res.data.errCode === h.errCode) // 判断 错误编码是否匹配
          h.action(res.data,params) // 回调
      })
    }
  }


  // 检查参数
  checkParams(params) {
    // console.log('throw error-------',params)
    if (!params.api) throw new Error("api没有设置")
  }
  completeSDK(e,params){
    // console.log('completeSDK-------',e,params)
    // setTimeout(()=>{
    //   Loading.service().close()
    // },500)
  }
}

export default new SDK()
